/*
 * @Description: Context
 * @Author: seadon
 * @LastEditors: seadon
 * @Date: 2021-04-16 16:04:33
 * @LastEditTime: 2021-04-16 21:21:09
 */
import {
	InjectionKey,
	provide,
	inject,
	reactive,
	readonly as defineReadonly,
	UnwrapRef,
} from 'vue'

export interface CreateContextOptions {
	readonly?: boolean
	createProvider?: boolean
	native?: boolean
}

type ShallowUnwrap<T> = {
	[P in keyof T]: UnwrapRef<T[P]>
}

export function createContext<T>(
	context: any,
	key: InjectionKey<T> = Symbol(),
	options: CreateContextOptions = {}
) {
	const { readonly = true, createProvider = false, native = false } = options

	const state = reactive(context)
	const provideData = readonly ? defineReadonly(state) : state
	!createProvider && provide(key, native ? context : provideData)
	return {
		state,
	}
}

export function useContext<T>(key: InjectionKey<T>, native?: boolean): T
export function useContext<T>(
	key: InjectionKey<T>,
	defaultValue?: any,
	native?: boolean
): T

export function useContext<T>(
	key: InjectionKey<T> = Symbol(),
	defaultValue?: any
): ShallowUnwrap<T> {
	return inject(key, defaultValue || {})
}
